package org.fastsyncer.core.util;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.fastsyncer.common.constant.ConnectorConstant;
import org.fastsyncer.common.entity.DatabaseConfig;
import org.fastsyncer.common.entity.LdapConfig;
import org.fastsyncer.common.entity.Mapping;
import org.fastsyncer.common.entity.RedisConfig;
import org.fastsyncer.common.entity.WebServiceConfig;
import org.fastsyncer.connector.framework.Database;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public abstract class ParseDriverCommon {

    private static Logger logger = LoggerFactory.getLogger(ParseDriverCommon.class);
    
    /**
     * 解析数据库配置
     * 
     * @Title: getDataSource
     * @Description: 解析数据库配置
     * @param datasource
     * @return: DataSourceConfig
     * @throws JSONException
     */
    protected static DatabaseConfig getDataSource(JSONObject ds) throws JSONException {
        String driverClassName = ds.getString("driverClassName");
        String url = ds.getString("url");
        String username = ds.getString("username");
        String password = ds.getString("password");
        String table = ds.isNull("table") ? null : ds.getString("table");
        String primaryKey = ds.getString("primaryKey");
        String sql = ds.isNull("sql") ? null : ds.getString("sql").toUpperCase();
        DatabaseConfig dataSourceConfig = new DatabaseConfig(driverClassName, url, table, primaryKey, username, password, sql);

        // 解析表列名属性
        JSONArray column = ds.getJSONArray("column");
        int colLen = column.length();
        if (column != null && colLen > 0) {
            List<Map<String, Object>> cols = new ArrayList<>();
            for (int i = 0; i < colLen; i++) {
                HashMap<String, Object> col = new HashMap<>();
                JSONObject c = (JSONObject) column.get(i);
                col.put("name", c.get("name"));
                col.put("typeName", c.get("typeName"));
                col.put("type", c.get("type"));
                cols.add(col);
            }
            dataSourceConfig.setColumn(cols);
        }
        return dataSourceConfig;
    }

    /**
     * 解析WebService配置
     * 
     * @Title: getWebService
     * @Description: 解析WebService配置
     * @param xml
     * @return: XMLConfig
     * @throws JSONException
     */
    protected static WebServiceConfig getWebService(JSONObject xml) throws JSONException {
        String url = (String) xml.get("url");
        String method = (String) xml.get("method");
        String primaryKey = (String) xml.get("primaryKey");
        WebServiceConfig xmlConfig = new WebServiceConfig(url, method, primaryKey);

        // 解析表列名属性
        JSONArray column = xml.getJSONArray("column");
        int colLen = column.length();
        if (column != null && colLen > 0) {
            List<HashMap<String, Object>> cols = new ArrayList<>();
            for (int i = 0; i < colLen; i++) {
                HashMap<String, Object> col = new HashMap<>();
                JSONObject c = (JSONObject) column.get(i);
                col.put("name", c.get("name"));
                col.put("typeName", c.get("typeName"));
                col.put("type", c.get("type"));
                cols.add(col);
            }
            xmlConfig.setColumn(cols);
        }
        return xmlConfig;
    }
    
    /**
     * 解析getLdap配置
     * 
     * @Title: getLdap
     * @Description: 解析getLdap配置
     * @param ldap
     * @return: ldapConfig
     * @throws JSONException
     */
    protected static LdapConfig getLdap(JSONObject ldap) throws JSONException {
        String url = ldap.getString("url");
        String base = ldap.getString("base");
        String userDn = ldap.getString("userDn");
        String password = ldap.getString("password");
        String dn = ldap.getString("dn");
        String searchScope = ldap.getString("searchScope");
        LdapConfig ldapConfig = new LdapConfig(url, base, userDn, password, dn, searchScope);

        // 解析继承对象
        JSONArray eObjects = ldap.getJSONArray("extendObjects");
        int eLen = eObjects.length();
        List<String> extendObjects = new ArrayList<String>(eLen);
        for (int i = 0; i < eLen; i++) {
            extendObjects.add(eObjects.getString(i));
        }
        ldapConfig.setExtendObjects(extendObjects);

        // 解析表列名属性
        JSONArray column = ldap.getJSONArray("column");
        int colLen = column.length();
        if (column != null && colLen > 0) {
            List<HashMap<String, Object>> cols = new ArrayList<>();
            for (int i = 0; i < colLen; i++) {
                HashMap<String, Object> col = new HashMap<>();
                JSONObject c = (JSONObject) column.get(i);
                col.put("name", c.get("name"));
                col.put("typeName", c.get("typeName"));
                col.put("type", c.get("type"));
                cols.add(col);
            }
            ldapConfig.setColumn(cols);
        }
        return ldapConfig;
    }
    
    /**
     * 解析getRedis配置
     * 
     * @Title: getRedis
     * @Description: 解析getRedis配置
     * @param redis
     * @return: redisConfig
     * @throws JSONException
     */
    protected static RedisConfig getRedis(JSONObject config) throws JSONException {
        String password = config.getString("password");
        String key = config.getString("key");
        String url = config.getString("url");
        RedisConfig redisConfig = new RedisConfig(url,key,password);

        // 解析表列名属性
        List<Map<String, Object>> cols = new ArrayList<>();
        if(!config.isNull("column")){
            JSONArray column = config.getJSONArray("column");
            int colLen = column.length();
            if (column != null && colLen > 0) {
                for (int i = 0; i < colLen; i++) {
                    Map<String, Object> col = new HashMap<>();
                    JSONObject c = (JSONObject) column.get(i);
                    col.put("name", c.get("name"));
                    col.put("typeName", c.get("typeName"));
                    col.put("type", c.get("type"));
                    cols.add(col);
                }
            }
        }
        redisConfig.setColumn(cols);
        return redisConfig;
    }
    
    /**
     * 解析同步属性
     * 
     * @Title: parseFields
     * @Description: 解析同步属性
     * @param filedsArray
     * @return: List<HashMap<String,Object>>
     * @throws JSONException
     */
    protected static List<Map<String, Object>> parseFields(JSONArray filedsArray) throws JSONException {
        List<Map<String, Object>> sourceFileds = new ArrayList<Map<String, Object>>();
        int sLen = filedsArray.length();
        for (int i = 0; i < sLen; i++) {
            JSONObject object = filedsArray.getJSONObject(i);
            Map<String, Object> sfiled = new HashMap<String, Object>();
            sfiled.put("name", object.get("name"));
            sfiled.put("type", object.get("type"));
            sfiled.put("typeName", object.get("typeName"));
            sourceFileds.add(sfiled);
        }
        return sourceFileds;
    }
    
    protected static void parseTargetDBExecuteCommond(List<Map<String, Object>> fileds, Mapping mapping, DatabaseConfig config, Database connector){
        String executeCommond = null;
        if (fileds != null && !fileds.isEmpty()) {
            Map<String, String> cmds = mapping.getExecuteCommond();
            // 1.解析插入语句
            executeCommond = connector.getJdbcSQL(ConnectorConstant.OPERTION_INSERT, config, fileds, null);
            cmds.put(ConnectorConstant.OPERTION_INSERT, executeCommond);
            logger.info("targetExecuteInsertCommond:" + executeCommond);

            // 2.解析修改语句
            executeCommond = connector.getJdbcSQL(ConnectorConstant.OPERTION_UPDATE, config, fileds, null);
            cmds.put(ConnectorConstant.OPERTION_UPDATE, executeCommond);
            logger.info("targetExecuteUpdateCommond:" + executeCommond);

            // 3.解析删除语句
            executeCommond = connector.getJdbcSQL(ConnectorConstant.OPERTION_DELETE, config, fileds, null);
            cmds.put(ConnectorConstant.OPERTION_DELETE, executeCommond);
            logger.info("targetExecuteDeleteCommond:" + executeCommond);
        }
    }
    
}
